package cn.com.bluemoon.daps.standard.excel.easypoi;

import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import cn.com.bluemoon.daps.common.enums.ReferRulesType;
import cn.com.bluemoon.daps.common.enums.StandardDataType;
import cn.com.bluemoon.daps.standard.entity.DapSystemCategory;
import cn.com.bluemoon.daps.standard.excel.BaseCacheVerifyHandler;
import cn.com.bluemoon.daps.standard.vo.BasicStandardAndDicVo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.io.Closeable;
import java.util.*;

/**
 * @author Jarod.Kong
 * @date 2020/8/26 17:21
 */
@Slf4j
public class BasicStandardVerifyHandler extends BaseCacheVerifyHandler
        implements IExcelVerifyHandler<BasicStandardAndDicVo>, Closeable {
    /**
     * 有序的中文名称
     */
    private static final List<String> HAD_READ_STANDARD_NAMES = Lists.newArrayList();
    /**
     * 有序的英文名称
     */
    private static final List<String> HAD_READ_STANDARD_ENG_NAMES = Lists.newArrayList();
    /**
     * 数据库中的已发布的标准中英文db
     */
    private final Set<String> dbPublishedStandardNames;
    private final Set<String> dbPublishedStandardEngNames;
    private List<DapSystemCategory> systemTopics;
    private List<DapSystemCategory> systemCategories;
    private Map<String, String> departAndIdMap;

    public BasicStandardVerifyHandler(Set<String> dbPublishedStandardNames, Set<String> dbPublishedStandardEngNames) {
        this.dbPublishedStandardEngNames = Optional.ofNullable(dbPublishedStandardEngNames).orElseGet(Sets::newHashSet);
        this.dbPublishedStandardNames = Optional.ofNullable(dbPublishedStandardNames).orElseGet(Sets::newHashSet);
    }

    /**
     * 导入校验方法
     *
     * @param obj 当前对象
     * @return
     */
    @Override
    public ExcelVerifyHandlerResult verifyHandler(BasicStandardAndDicVo obj) {
        int currentRowIndex = sheetRowIndex.incrementAndGet();
        if (obj != null) {
            // 针对标准中文名称校验
            String uniqueKey = obj.getName();
            int rowIndex = HAD_READ_STANDARD_NAMES.indexOf(uniqueKey);
            HAD_READ_STANDARD_NAMES.add(uniqueKey);
            List<String> errorMsgs = Lists.newArrayList();
            String errorMsg = null;
            if (rowIndex >= 0) {
                errorMsg = String.format("第%d行与前第%d行的[中文名称]列值一样", currentRowIndex, rowIndex + 2);
                errorMsgs.add(errorMsg);
            }
            if (dbPublishedStandardNames.contains(uniqueKey)) {
                errorMsg = String.format("第%d行的[中文名称]列值，系统标准中已存在", currentRowIndex);
                errorMsgs.add(errorMsg);
            }
            // 针对标准英文名称校验
            uniqueKey = obj.getEngName();
            rowIndex = HAD_READ_STANDARD_ENG_NAMES.indexOf(uniqueKey);
            HAD_READ_STANDARD_ENG_NAMES.add(uniqueKey);
            if (rowIndex >= 0) {
                errorMsg = String.format("第%d行与前第%d行的[英文名称]列值一样", currentRowIndex, rowIndex + 2);
                errorMsgs.add(errorMsg);
            }
            if (dbPublishedStandardEngNames.contains(uniqueKey)) {
                errorMsg = String.format("第%d行的[英文名称]列值，系统标准中已存在", currentRowIndex);
                errorMsgs.add(errorMsg);
            }
            Optional.ofNullable(obj.getDepartmentName()).ifPresent(s -> obj.setDepartmentId(departAndIdMap.getOrDefault(StringUtils.trim(s), null)));
            String referRulesContent = obj.getReferRulesContent();
            ReferRulesType referRulesType = ReferRulesType.ofDesc(referRulesContent).orElse(ReferRulesType.OTHER_STD);
            obj.setReferRules(referRulesType);
            String dataTypeStr = obj.getDataTypeStr();
            if (StringUtils.isBlank(dataTypeStr)) {
                errorMsg = String.format("第%d行的[数据类型]列值，不可为空", currentRowIndex);
                errorMsgs.add(errorMsg);
            } else {
                try {
                    StandardDataType dataType = Enum.valueOf(StandardDataType.class, dataTypeStr);
                    obj.setDataType(dataType);
                } catch (Exception e) {
                    errorMsg = String.format("第%d行的[数据类型]列值，不符合定义规范", currentRowIndex);
                    log.error(errorMsg);
                    errorMsgs.add(errorMsg);
                }
            }
            // 获取topicId,primaryCategory,departmentid 为空则失败
            Optional<DapSystemCategory> topicObj = systemTopics.stream()
                    .filter(o -> o.getCodeName().equalsIgnoreCase(StringUtils.trim(obj.getTopicName()))).findAny();
            if (!topicObj.isPresent()) {
                errorMsg = String.format("第%d行的[主题]列值与系统主题分类匹配失败", obj.getRowNum() + 1);
                errorMsgs.add(errorMsg);
            } else {
                String topicId = topicObj.get().getId();
                obj.setTopicId(topicId);
                Optional<DapSystemCategory> category1Obj = systemCategories.stream().filter(o -> o.getParentId().equals(topicId))
                        .filter(o -> o.getCodeName().equalsIgnoreCase(obj.getFirstCategoryName())).findFirst();
                if (!category1Obj.isPresent()) {
                    errorMsg = String.format("第%d行的[一级分类]列值与系统主题分类匹配失败", obj.getRowNum() + 1);
                    errorMsgs.add(errorMsg);
                } else {
                    String category1Id = category1Obj.get().getId();
                    obj.setFirstCategory(category1Id);
                    // 处理二/三级分类
                    List<DapSystemCategory> nextNodes = category1Obj.get().getNextNodes();
                    if (nextNodes != null && !nextNodes.isEmpty()) {
                        DapSystemCategory category2Obj = nextNodes.stream().filter(o -> o.getCodeName().equalsIgnoreCase(StringUtils.trim(obj.getSecondCategoryName()))).findFirst().orElse(new DapSystemCategory());
                        obj.setSecondCategoryName(category2Obj.getId());
                        List<DapSystemCategory> nextNodes2 = category2Obj.getNextNodes();
                        if (nextNodes2 != null && !nextNodes2.isEmpty()) {
                            DapSystemCategory category3Obj = nextNodes2.stream().filter(o -> o.getCodeName().equalsIgnoreCase(StringUtils.trim(obj.getSecondCategoryName()))).findFirst().orElse(new DapSystemCategory());
                            obj.setThirdCategoryName(category3Obj.getId());
                        }
                    }
                }
            }
            if (!errorMsgs.isEmpty()) {
                return new ExcelVerifyHandlerResult(false, String.join("；", errorMsgs));
            }
        }
        return new ExcelVerifyHandlerResult(true);
    }

    @Override
    public void close() {
        dbPublishedStandardEngNames.clear();
        dbPublishedStandardNames.clear();
        HAD_READ_STANDARD_ENG_NAMES.clear();
        HAD_READ_STANDARD_NAMES.clear();
    }

    @Override
    public Map<String, Object> getSheetCacheMap() {
        return null;
    }

    public BasicStandardVerifyHandler setTopices(List<DapSystemCategory> systemTopics) {
        //noinspection AliControlFlowStatementWithoutBraces
        if (systemTopics == null) {
            systemTopics = Collections.emptyList();
        }
        this.systemTopics = systemTopics;
        return this;
    }

    public BasicStandardVerifyHandler setCategories(List<DapSystemCategory> systemCategories) {
        //noinspection AliControlFlowStatementWithoutBraces
        if (systemCategories == null) {
            systemCategories = Collections.emptyList();
        }
        this.systemCategories = systemCategories;
        return this;
    }

    public BasicStandardVerifyHandler setDepartment(Map<String, String> departAndIdMap) {
        //noinspection AliControlFlowStatementWithoutBraces
        if (departAndIdMap == null) {
            departAndIdMap = Collections.emptyMap();
        }
        this.departAndIdMap = departAndIdMap;
        return this;
    }
}